import { Response, ServiceConfig, route, Guid, Logger, RequestLog } from '../common';
import { CloudSyncService } from '../service/cloudSyncService';
import { FrontStoreStockService } from '../service/frontStoreStockService';
import { ProduceRecordService } from '../service/produceRecordService';
import { KitchensolutionService } from '../service/kitchensolutionService';
import { ProduceRecord, } from '../domain/model';
import { WebException } from './webException';
import { RequestDataVerify } from '../common/http/router/routeDecorators';
import { DataVerification } from "./verification/baseVerification";
import { VerificationException } from './verification/verificationException';
import { FNS } from '../common/fnc/fncManager';
import { InventoryService } from "../service/inventoryService";

let lodash = require('lodash');

export class FrontStoreStockController {
    private syncSvr: CloudSyncService;
    private frontStoreStockSvr: FrontStoreStockService;
    private produceRecordSrc: ProduceRecordService;
    private kitchensolutionSvc: KitchensolutionService;
    private inventorySvr: InventoryService;
    constructor() {
        this.syncSvr = ServiceConfig.Current.GetService<CloudSyncService>("cloudSyncService");
        this.frontStoreStockSvr = ServiceConfig.Current.GetService<FrontStoreStockService>("frontStoreStockService");
        this.produceRecordSrc = ServiceConfig.Current.GetService<ProduceRecordService>("produceRecordService");
        this.kitchensolutionSvc = ServiceConfig.Current.GetService<KitchensolutionService>("kitchensolutionService");
        this.inventorySvr = ServiceConfig.Current.GetService<InventoryService>("inventoryService");
    }

    toString() {
        return "FrontStoreStockController";
    }


    /**
     * 使用厨房解决方案 Id 获取门店前店库存
     * 
     * @param {any} ctx 
     * @param {any} next 
     * 
     * @memberof FrontStoreStockController
     */
    @route({ method: 'get', path: '/api/frontStoreStocks/:kitchenSolutionId/getFrontStoreStocks' })
    async getFrontStoreStocks(ctx, next) {
        let storeId = ctx.accept.headers["storeid"];
        let kitchenSolutionId = ctx.params.kitchenSolutionId;
        let startTime = ctx.query.startTime;
        let endTime = ctx.query.endTime;
        if (!startTime || !endTime)
            throw new VerificationException(
                'ctx.query.startTime || ctx.query.endTime',
                "开始时间和结束时间不能为空"
            )
        let inventories = [];
        if (kitchenSolutionId == 'all') {
            inventories = await this.inventorySvr.GetAll();
        } else {
            let kitchenSolution = await this.kitchensolutionSvc.GetKitchensolutionById(kitchenSolutionId);
            if (!kitchenSolution) throw new WebException("厨显方案不存在");
            inventories = kitchenSolution.inventories;
        }
        if (!inventories) throw new WebException("该厨显方案没有选择菜品");
        if (inventories && inventories.length == 0) throw new WebException("该厨显方案没有选择菜品");
        let ids = lodash.map(inventories, 'id');

        let frontStoreStocks: any = await this.frontStoreStockSvr.GetStocksByInventoryIds(storeId, ids, startTime, endTime);
        ctx.response.body = Response.ok("获取门店前端库存成功", frontStoreStocks);
        await next();
    }


    /**
     * 制作商品
     * 
     * @param {any} ctx 
     * @param {any} next 
     * 
     * @memberof FrontStoreStockController
     */
    @route({ method: 'put', path: '/api/frontStoreStocks/:frontStoreStockId/augmentFrontStoreStock' })
    @RequestLog()
    @RequestDataVerify(new DataVerification.augmentFrontStoreStockVerify())
    async augmentFrontStoreStock(ctx, next) {
        // TODO 该业务需要一个事务，目前数据上下文件对象功能无法满足
        let frontStoreStockId = ctx.params.frontStoreStockId;
        let storeId = ctx.accept.headers["storeid"];
        let obj = ctx.request.body;
        let frontStoreStock = obj.frontStoreStock;
        let terminal = obj.terminal;
        let producerRecord = obj.producerRecord;
        let inventory = obj.producerRecord.inventory;
        let producer = obj.producerRecord.producer;
        let creator = obj.producerRecord.creator;
        let beginTime = obj.producerRecord.beginTime;
        let endTime = obj.producerRecord.endTime;

        frontStoreStock.storeId = storeId;
        frontStoreStock.inventoryId = inventory.id;
        let updatedStock: any = await this.frontStoreStockSvr.AugmentFrontStoreStock(
            frontStoreStock
        );
        if (updatedStock) {
            // 修改数据成功以后添加一条制作记录
            let record = new ProduceRecord();
            record.storeId = storeId;
            record.inventory = inventory;
            record.inventoryId = inventory.id;
            record.terminal = terminal;
            record.terminalId = terminal.id;
            record.producer = producer;
            record.producerId = producer.id;
            record.creator = creator;
            record.creatorId = creator.id;
            record.beginTime = beginTime;
            record.endTime = endTime;
            record.quantity = frontStoreStock.quantity;
            await this.produceRecordSrc.createProduceRecord(record);
            updatedStock.produceRecord = record;
            // 通知其他终端
            FNS.FNCManager.Current.Notify(new FNS.SoldOutMessage([{
                id: frontStoreStockId,
                isSoldOut: false,
                soldOutMode: 'manual',
                quantity: updatedStock.quantity
            }]));
        }

        ctx.response.body = Response.ok("制作成功", updatedStock);



        // 上传制作纪录
        this.syncSvr.DomainDataSyncPackage(
            [{
                id: updatedStock.produceRecord.id,
                body: updatedStock.produceRecord,
                entityName: "produceRecords"
            }],
            {
                storeId: storeId,
                terminal: terminal,
                user: creator
            }
        );


        await next();
    }


    /**
     * 门店前端库存卖完沽清（制作台使用）
     * 
     * @param {any} ctx 
     * @param {any} next 
     * 
     * @memberof FrontStoreStockController
     */
    @route({ method: 'put', path: '/api/frontStoreStocks/:frontStoreStockId/setSoldOut' })
    async setSoldOut(ctx, next) {
        let frontStoreStockId = ctx.params.frontStoreStockId;
        let storeId = ctx.accept.headers["storeid"];
        let updatedStock = await this.frontStoreStockSvr
            .setFrontStoreStockSoldOut(frontStoreStockId);
        ctx.response.body = Response.ok("设置售完沽清成功", updatedStock);
        FNS.FNCManager.Current.Notify(new FNS.SoldOutMessage([{
            id: frontStoreStockId,
            isSoldOut: updatedStock.isSoldOut,
            soldOutMode: updatedStock.soldOutMode
        }]));
        await next();
    }

    /**
     * 门店前端库存卖完沽清（POS端使用）
     * 
     * @param {any} ctx 
     * @param {any} next 
     * 
     * @memberof FrontStoreStockController
     */
    @route({ method: 'put', path: '/api/frontStoreStocks/:inventoryId/setSoldOutManualMode' })
    async setSoldOutManualMode(ctx, next) {
        let inventoryId = ctx.params.inventoryId;
        let storeId = ctx.accept.headers["storeid"];
        let updatedStock = await this.frontStoreStockSvr.setFrontStoreStockManual(inventoryId);
        ctx.response.body = Response.ok("手动沽清成功", updatedStock);
        FNS.FNCManager.Current.Notify(new FNS.SoldOutMessage([{
            id: inventoryId,
            isSoldOut: true,
            soldOutMode: "manual"
        }]));
        await next();
    }

    /**
     * 获取某商品沽清状态（POS端使用）
     * 
     * @param {any} ctx 
     * @param {any} next 
     * 
     * @memberof FrontStoreStockController
     */
    @route({ method: 'get', path: '/api/frontStoreStocks/:inventoryId/getSoldOutByInventoryId' })
    async getSoldOutByInventoryId(ctx, next) {
        let inventoryId = ctx.params.inventoryId;
        let stock = await this.frontStoreStockSvr.getSoldOutByInventoryId(inventoryId);
        let result = null;
        if (stock) {
            result = {
                id: stock.id,
                inventoryId: stock.inventoryId,
                operTime: stock.soldOutTime
            }
        }

        ctx.response.body = Response.ok("获取成功", result);
        await next();
    }

    /**
     * 取消门店前端库存卖完沽清
     * 
     * @param {any} ctx 
     * @param {any} next 
     * 
     * @memberof FrontStoreStockController
     */
    @route({ method: 'put', path: '/api/frontStoreStocks/cancelSoldOut' })
    async cancelSoldOut(ctx, next) {
        let frontStoreStockIds: string[] = ctx.request.body.frontStoreStockIds;
        let storeId = ctx.accept.headers["storeid"];
        let updatedStock = await this.frontStoreStockSvr.cancelFrontStoreStockSoldOut(frontStoreStockIds);
        let soldOutList = [];
        for (let frontStoreStockId of frontStoreStockIds) {
            soldOutList.push({
                id: frontStoreStockId,
                isSoldOut: false,
                soldOutMode: "manual"
            });
        }
        ctx.response.body = Response.ok("取消沽清成功", soldOutList);
        if (soldOutList.length > 0) FNS.FNCManager.Current.Notify(new FNS.SoldOutMessage(soldOutList));
        await next();
    }
}